#ifndef METADATACLASE_H
#define METADATACLASE_H

#include <list>
#include <map>
#include <iostream>
#include <string>
#include <sstream>
#include "Archivo.h"


using namespace std;

namespace Comun
{
	
	enum OrgRegistros
	{
		iRVB,
		iRF
	};
	
	enum ImplementIndice
	{
		iHash,
		iArbolBPlus
	};

	enum TipoIntegridad
	{
		iAlta,
		iBaja
	};
	
	class InfoIndice
	{
		
		private:
		
		ImplementIndice _ImplemIndice;
		list<string> _Campos;
		int _TamanioNodo;
		unsigned int _TamanioInicial;
		unsigned int _TamanioBucket;
		bool _Primario;
		
		public:

		
		
		void setPrimario(bool valor)
		{
			_Primario=valor;
		}
		
		bool esPrimario()
		{
			return _Primario;
		}
		
		void setArbolBP(int TamNodo)
		{
			_ImplemIndice=iArbolBPlus;
			_TamanioNodo=TamNodo;
			_TamanioInicial=0;
			_TamanioBucket=0;
		}
		
		void setHash(unsigned int TamInicial,unsigned int TamBuck)
		{
			_ImplemIndice=iHash;
			_TamanioInicial=TamInicial;
			_TamanioBucket=TamBuck;
			_TamanioNodo=0;
		}
		
		void addCampo(string campo)
		{
			_Campos.push_back(campo);
		}
		
		ImplementIndice getTipoImplementacion()
		{
			return _ImplemIndice;
		}
		
		list<string>& getCampos()
		{
			return _Campos;
		}
		
		int getTamanioNodo()
		{
			return _TamanioNodo;
		}
		
		unsigned int getTamanioInicial()
		{
			return _TamanioInicial;
		}
		
		unsigned int getTamanioBucket()
		{
			return _TamanioBucket;
		}
		
	};
	
	class AtributoClase
	{
		
		private:
		
		string _Nombre;
		TipoRegistro _TipoAtrb;
		
		public:
		
		void setNombre(string NombAtr)
		{
			_Nombre=NombAtr;
		}
			
		void setTipo(TipoRegistro Tipo)
		{
			_TipoAtrb=Tipo;
		}
		
		string getNombre()
		{
			return _Nombre;
		}
		
		TipoRegistro getTipo()
		{
			return _TipoAtrb;
		}
		
	};
	
	class RelacionIntegridad
	{
	
		private:
		
		string _NombreCampo;
		string _NombreClase;
		string _NombreCampoClaseExterna;
		TipoIntegridad _TipoIntegridad;

		
		public:
			
		void setNombreCampo(string NombCamp)
		{
			_NombreCampo=NombCamp;
		}
		
		void setNombreClase(string NombClase)
		{
			_NombreClase=NombClase;
		}

		void setTipoIntegridad(TipoIntegridad TipoI)
		{
			_TipoIntegridad=TipoI;
		}

		void setNombreCampoClaseExterna(string NombCampoClaseExt)
		{
			_NombreCampoClaseExterna=NombCampoClaseExt;
		}
		
		string getNombreCampo()
		{
			return _NombreCampo;
		}
		
		string getNombreClase()
		{
			return _NombreClase;
		}

		TipoIntegridad getTipoIntegridad()
		{
			return _TipoIntegridad;
		}

		string getNombreCampoClaseExterna()
		{
			return _NombreCampoClaseExterna;
		}
	};
	
	class MetadataClase
	{
	
		private:
		
		string _Clase;
		OrgRegistros _OrganizacionReg;
		list<AtributoClase> _Atributos;
		InfoIndice* _IndicePrimario;
		list<InfoIndice*> _IndicesSecundarios;
		list<RelacionIntegridad> _RelacionesIntegridad;
		
		MetadataClase();
		void setClase(string Clase);
		void setOrganizacionReg(OrgRegistros OrgReg);
		void addAtributo(const AtributoClase& atr);
		void addRelacionIntegridad(const RelacionIntegridad& RI);
		void setIndicePrimario(InfoIndice* IndicePrim);
		void addIndiceSecundario(InfoIndice* IndiceSec);
		
		public:
		
		~MetadataClase();
		string getClase();
		OrgRegistros getOrganizacionReg();
		list<AtributoClase>& getAtributos();
		list<RelacionIntegridad>& getRelacionesIntegridad();
		InfoIndice* getIndicePrimario();
		list<InfoIndice*>& getIndicesSecundarios();
		TipoRegistro getTipoAtributo(string nombreAtrib);
		bool hayIndiceCampo(string NombreCampo);
		bool esIndicePrimario(string NombreCampo);
		bool esIndiceSecundario(string NombreCampo);
		bool campoExiste(string NombreCampo);
		static MetadataClase* hidratarDesdeLista(list<string> ListaInfo);
		static MetadataClase* hidratarDesdeStream(stringstream* streamInfo);
	
		private:
	
		static ImplementIndice hidratarTipoIndice(string str);
		static OrgRegistros hidratarOrganizaciondeReg(string str);
		static AtributoClase hidratarAtributo(string val[]);
		static TipoRegistro hidratarTipoVar(string str);
		static InfoIndice* hidratarIndice(string val[],bool Primario);
		static string hidratarNombreClase(string str);
		static RelacionIntegridad hidratarRelacionIntegridad(string val[]);
		static TipoIntegridad hidratarTipoIntegridad(string val);
		
	};
}

#endif
